/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/container_impl.h"
#include "../data_struct/webapp.h"
#include "app_listener.h"

namespace cat
{

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    app_listener::app_listener( webapp * pWebApp ) : m_pWebApp( pWebApp )
    {
    }

    app_listener::~app_listener()
    {
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int app_listener::load_listeners( xos_common::i_property * pListeners, icat::i_listener * pListener )
    {
        int ret = 0;

        xos_common::i_variant * pListen = 0;
        const char * lpszListenType = 0;

        if( 0 == ret )
        {
            pListeners->reset();
        }

        while( ( 0 == ret ) && ( pListen = pListeners->name_data( &lpszListenType, 0, 0, 0 ) ) )
        {
            xos_common::i_property * pProp = ( xos_common::i_property * )pListen->obj( 0 );
            pProp->reset();
            load_listen( lpszListenType, pProp, pListener );
            pListeners->name_next();
        }

        return ret;
    }

    int app_listener::load_listen( const char * lpszListenType, xos_common::i_property * pListen, icat::i_listener * pListener )
    {
        int ret = 0;
        xos_common::i_variant * pEvent = 0;
        const char * lpszEventType = 0;
        while( ( pEvent = pListen->name_data( &lpszEventType, 0, 0, 0 ) ) )
        {
            xos_common::i_property * pProp = ( xos_common::i_property * )pEvent->obj( 0 );
            pProp->reset();
            load_event( lpszListenType, lpszEventType, pProp, pListener );
            pListen->name_next();
        }
        return ret;
    }

    int app_listener::load_event( const char * lpszListenType, const char * lpszEventType, xos_common::i_property * pEvent, icat::i_listener * pListener )
    {
        int ret = 0;

        webapp::LISTENER_MAP & mp = *m_pWebApp->m_pListenerMap;
        typedef webapp::LISTENER_MAP::iterator ITER;

        xos_common::i_variant * pAdvise = 0;
        const char * lpszAdvise = 0;
        char buf[256];

        while( ( pAdvise = pEvent->name_data( &lpszAdvise, 0, 0, 0 ) ) )
        {
            container_impl::get()->xos()->crt()->sprintf( buf, sizeof( buf ), "%s.%s.%s", lpszListenType, lpszEventType, lpszAdvise );
            ITER iter = mp.find( buf );
            webapp::LISTENER_LIST * pList = 0;
            if( iter == mp.end() )
            {
                xos_stl::init_obj( pList );
                mp[buf] = pList;
            }
            else
            {
                pList = iter->second;
            }
            pList->push_back( pListener );
            pEvent->name_next();
        }

        return ret;
    }

    icat::i_plugin::enumRetCode app_listener::call_listeners( icat::i_plugin::enumRetCode result, 
        icat::i_task * pTask, 
        const char * lpszType, 
        const char * lpszEvent, 
        const char * lpszAdvise )
    {
        int ret = 0;

        typedef webapp::LISTENER_LIST::iterator LIST_ITER;
        typedef webapp::LISTENER_MAP::iterator MAP_ITER;
        webapp::LISTENER_MAP & mp = *m_pWebApp->m_pListenerMap;

        icat::i_chain * pChain = pTask->get_chain();
        webapp::LISTENER_LIST * pList = 0;

        if( ( 0 == ret ) && ( icat::i_plugin::RET_CODE_DONE != result ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            char buf[256] = { 0 };
            container_impl::get()->xos()->crt()->sprintf( buf, sizeof( buf ), "%s.%s.%s", lpszType, lpszEvent, lpszAdvise );
            MAP_ITER iter = mp.find( buf );
            if( iter != mp.end() )
            {
                pList = iter->second;
            }
            if( !pList )
            {
                ret = 1;
            }
        }

        if( 0 != ret )
        {
            return result;
        }

        pChain->set_listen_event( lpszType, lpszEvent, lpszAdvise );

        for( LIST_ITER iter = pList->begin(); ( icat::i_plugin::RET_CODE_DONE == result ) && ( iter != pList->end() ); ++iter )
        {
            icat::i_listener * pL = *iter;
            result = pL->proc( pTask );
        }

        pChain->set_listen_event( 0, 0, 0 );

        return result;
    }

} // cat
